home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
intrlib1.zip
/
PU_MENUS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-26
|
15KB
|
399 lines
/******************************************************************************
* Iteraction library - pop up menus handler. *
* *
* Written by Gershon Elber, Oct. 1990 *
*******************************************************************************
* History: *
* 3 Oct 90 - Version 1.0 by Gershon Elber. *
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>
#include "intr_loc.h"
#include "intr_gr.h"
#define POP_UP_BORDER 10
#ifdef DJGCC
#define POP_UP_BASE_LINE 16
#else
#define POP_UP_BASE_LINE 12
#endif /* DJGCC */
static int GRLastColor = 0; /* GR Color set before query. */
static IntrBType HasHeader = FALSE;
static void MenuProlog(IntrCursorShapeStruct *Cursor,
int MenuWidth, int MenuHeight, int Top, int Left,
int FrameWidth,
IntrColorType FrameColor, IntrColorType BackColor,
int *Xmin, int *Ymin, int *Xmax, int *Ymax);
static void MenuEpilog(void);
static void IntrPopUpMenuDrawItems(IntrPopUpMenuStruct *PUMenu,
int Top,
int Left);
static int MatchPosition(int x, int y, int Top, int Left,
int Bottom, int Right, int Space, int ItemHeight);
/****************************************************************************
* Save current graphic state. *
****************************************************************************/
static void MenuProlog(IntrCursorShapeStruct *Cursor,
int MenuWidth, int MenuHeight, int Top, int Left,
int FrameWidth,
IntrColorType FrameColor, IntrColorType BackColor,
int *Xmin, int *Ymin, int *Xmax, int *Ymax)
{
/* Save current graphic state. */
IntrPushCursorType();
IntrSetCursorType(Cursor);
GRPushViewPort();
_GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);
GRPushTextSetting();
GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_BOTTOM);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
GRLastColor = GRGetColor();
*Xmin = Left;
*Ymin = Top;
*Xmax = Left + MenuWidth;
*Ymax = Top + MenuHeight;
_IntrBoundBBox(Xmin, Ymin, Xmax, Ymax, FrameWidth); /* To screen coords. */
_IntrWndwDrawFrame(*Xmin, *Xmax, *Ymin, *Ymax, FrameWidth,
FrameColor, TRUE, FrameColor, INTR_SCRLBAR_NONE,
FrameColor, INTR_SCRLBAR_NONE, TRUE);
IntrAllocColor(BackColor, INTR_INTENSITY_HIGH);
GRSBar(*Xmin, *Ymin, *Xmax, *Ymax);
}
/****************************************************************************
* Restore current graphic state. *
****************************************************************************/
static void MenuEpilog(void)
{
if (_IntrSaveBelow) {
_IntrRestoreWindow();
if (HasHeader) {
_IntrRestoreWindow();
HasHeader = FALSE;
}
}
GRPopViewPort();
GRPopTextSetting();
GRSetColor(GRLastColor);
IntrPopCursorType();
}
/******************************************************************************
* Routine to free a pop up menu. *
******************************************************************************/
void IntrPopUpMenuDelete(IntrPopUpMenuStruct *PUMenu)
{
_IntrFree(PUMenu);
}
/******************************************************************************
* Routine to create a pop up menu. *
* If SizeOfEntry = 0 then StrEntries is an array of (char *). Otherwise it *
* holds the size of each entry in StrEntries which is a long string itself. *
* NumOfEntries defines the length of the menu. *
* It should be noted that in both cases StrEntries is NOT copied. *
******************************************************************************/
IntrPopUpMenuStruct *IntrPopUpMenuCreate(char *Header,
char **StrEntries,
int SizeOfEntry,
int NumOfEntries,
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
IntrColorType XorColor,
int FrameWidth,
IntrCursorShapeStruct *Cursor)
{
int i, MaxLen;
IntrPopUpMenuStruct *PUMenu;
PUMenu = (IntrPopUpMenuStruct *) _IntrMalloc(sizeof(IntrPopUpMenuStruct));
PUMenu -> Header = Header;
PUMenu -> ForeColor = ForeColor;
PUMenu -> BackColor = BackColor;
PUMenu -> FrameColor = FrameColor;
PUMenu -> XorColor = XorColor;
PUMenu -> FrameWidth = FrameWidth;
PUMenu -> NumOfEntries = NumOfEntries;
PUMenu -> SizeOfEntry = SizeOfEntry;
PUMenu -> StrEntries = StrEntries;
GEN_COPY(&PUMenu -> Cursor, Cursor, sizeof(IntrCursorShapeStruct));
/* Find width and height of menu using number of items and their */
/* maximum entry string length. */
if (SizeOfEntry == 0) { /* Its an array of pointers to strings. */
for (i = MaxLen = 0; i < NumOfEntries; i++)
if (MaxLen < strlen(StrEntries[i]))
MaxLen = strlen(StrEntries[i]);
}
else
MaxLen = SizeOfEntry;
GRPushTextSetting();
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
PUMenu -> _MenuWidth = GRGetTextWidth("M") * MaxLen + (POP_UP_BORDER << 1);
PUMenu -> _MenuHeight = POP_UP_BASE_LINE * NumOfEntries +
(POP_UP_BORDER << 1);
GRPopTextSetting();
return PUMenu;
}
/****************************************************************************
* Routine to change pop up menu entry i. Only menus defined using array of *
* strings can be modified in this way (PUMenu -> SizeOfEntry must be zero). *
****************************************************************************/
void IntrPopUpSetEntry(IntrPopUpMenuStruct *PUMenu, char *Entry, int Index)
{
if (PUMenu -> SizeOfEntry == 0)
PUMenu -> StrEntries[Index] = Entry;
else
strncpy((char *) &PUMenu -> StrEntries[Index * PUMenu -> SizeOfEntry],
Entry,
PUMenu -> SizeOfEntry - 1);
}
/****************************************************************************
* Routine to change pop up menu header. *
****************************************************************************/
void IntrPopUpSetHeader(IntrPopUpMenuStruct *PUMenu, char *Header)
{
PUMenu -> Header = Header;
}
/****************************************************************************
* Routine to change pop up menu frame width. *
****************************************************************************/
void IntrPopUpSetFrameWidth(IntrPopUpMenuStruct *PUMenu, int FrameWidth)
{
PUMenu -> FrameWidth = FrameWidth;
}
/****************************************************************************
* Routine to change pop up menu colors. *
****************************************************************************/
void IntrPopUpSetColors(IntrPopUpMenuStruct *PUMenu,
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
IntrColorType XorColor)
{
PUMenu -> ForeColor = ForeColor;
PUMenu -> BackColor = BackColor;
PUMenu -> FrameColor = FrameColor;
PUMenu -> XorColor = XorColor;
}
/****************************************************************************
* Routine to draw the given pop up menu items at the given position. *
****************************************************************************/
static void IntrPopUpMenuDrawItems(IntrPopUpMenuStruct *PUMenu,
int Left,
int Top)
{
int i, Color;
char *Str = (char *) PUMenu -> StrEntries;
Color = IntrAllocColor(PUMenu -> ForeColor, INTR_INTENSITY_VHIGH);
GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
Left += POP_UP_BORDER;
Top += POP_UP_BORDER;
for (i = 0; i < PUMenu -> NumOfEntries; i++) {
if (PUMenu -> SizeOfEntry > 0) {
GRSTextShadow(Left, Top + i * POP_UP_BASE_LINE, Color,
&Str[i * PUMenu -> SizeOfEntry]);
}
else {
GRSTextShadow(Left, Top + i * POP_UP_BASE_LINE, Color,
PUMenu -> StrEntries[i]);
}
}
}
/****************************************************************************
* Routine to attempt to match given location with one of the elements in *
* items displayed. Item are displayed from Top to Bottom, Left to Right. *
* Item is placed with Space between them and border, and has ItemHeight *
* height. *
* Returns the index that matches, or -1 if No match. *
****************************************************************************/
static int MatchPosition(int x, int y, int Top, int Left,
int Bottom, int Right, int Space, int ItemHeight)
{
int CurrentY, i;
/* Fast clipping if cursor is not in the menu at all. */
if (x <= Left || x >= Right || y <= Top || y >= Bottom) return -1;
for (i = 0, CurrentY = Top;
CurrentY < Bottom;
CurrentY += Space, i++) {
if (CurrentY <= y && CurrentY + ItemHeight >= y) return i;
}
return -1;
}
/****************************************************************************
* Routine to pop up a menu. *
* Return TRUE if was SELECT key, FALSE if ABORT key. *
* Attempt will be made to pop up the menu in the window specified or in a *
* screen location INTR_WNDW_PLACE_XXXX. *
* position may be modified so the entire pop up menu will be visible. *
* The selected index is saved in PUMenu structure, SelectedIndex entry. *
****************************************************************************/
int IntrPopUpMenu(IntrPopUpMenuStruct *PUMenu, int WindowID)
{
IntrBBoxStruct *BBox;
int MenuCenterX, MenuCenterY;
/* Find center of query prefered position and find BBox for query. */
if (WindowID > 0) {
BBox = IntrWndwGetBBox(WindowID);
MenuCenterX = (BBox -> Xmax + BBox -> Xmin) >> 1;
MenuCenterY = (BBox -> Ymax + BBox -> Ymin) >> 1;
}
else
switch (WindowID) {
case INTR_WNDW_PLACE_LEFT:
MenuCenterX = GRScreenMaxX >> 2;
MenuCenterY = GRScreenMaxY >> 1;
break;
case INTR_WNDW_PLACE_RIGHT:
MenuCenterX = (GRScreenMaxX >> 1) + (GRScreenMaxX >> 2);
MenuCenterY = GRScreenMaxY >> 1;
break;
case INTR_WNDW_PULL_DOWN:
if (_IntrAsyncLastEvent.AsyncEvent == ASYNC_EVNT_PDMENU) {
MenuCenterX = _IntrAsyncLastEvent.PDLeft +
PUMenu -> FrameWidth + (PUMenu -> _MenuWidth >> 1);
MenuCenterY = _IntrAsyncLastEvent.PDBottom +
PUMenu -> FrameWidth + (PUMenu -> _MenuHeight >> 1);
if (PUMenu -> Header != NULL)
MenuCenterY += IntrWndwGetHeaderHeight(
PUMenu -> Header, PUMenu -> FrameWidth) + 2;
_IntrAsyncLastEvent.AsyncEvent = ASYNC_EVNT_NONE;
break;
}
case INTR_WNDW_PLACE_CENTER:
default:
MenuCenterX = GRScreenMaxX >> 1;
MenuCenterY = GRScreenMaxY >> 1;
break;
}
return _IntrPopUpMenu(PUMenu,
MenuCenterX - (PUMenu -> _MenuWidth >> 1),
MenuCenterY - (PUMenu -> _MenuHeight >> 1));
}
/****************************************************************************
* Same as IntrPopUpMenu, but exact position is specified via Top/Left. *
****************************************************************************/
int _IntrPopUpMenu(IntrPopUpMenuStruct *PUMenu,
int Left,
int Top)
{
int x, y, Xmin, Xmax, Ymin, Ymax, Event, MatchIndex, NewIndex,
RetVal, ListLeft, ListTop, ListRight, ListBottom,
Exit = FALSE;
MenuProlog(&PUMenu -> Cursor,
PUMenu -> _MenuWidth, PUMenu -> _MenuHeight, Top, Left,
PUMenu -> FrameWidth, PUMenu -> FrameColor, PUMenu -> BackColor,
&Xmin, &Ymin, &Xmax, &Ymax);
ListLeft = Xmin + POP_UP_BORDER; /* Item list boundaries: */
ListTop = Ymin + POP_UP_BORDER;
ListRight = Xmax - POP_UP_BORDER;
ListBottom = Ymax - POP_UP_BORDER;
MatchIndex = -1; /* No match == -1. */
IntrPopUpMenuDrawItems(PUMenu, Xmin, Ymin);
if (PUMenu -> Header != NULL) {
HasHeader = TRUE;
_IntrWndwPutNameHeader(Xmin - PUMenu -> FrameWidth,
Xmax + PUMenu -> FrameWidth,
Ymin - PUMenu -> FrameWidth - 2,
PUMenu -> FrameWidth, PUMenu -> Header,
TRUE, PUMenu -> FrameColor,
PUMenu -> ForeColor, PUMenu -> BackColor,
TRUE);
}
Event = INTR_EVNT_MOVE;/* Emulate move event, and test current position. */
x = GRCurrentCursorX = (ListLeft + ListRight) >> 1;
y = GRCurrentCursorY = ListTop + (GRGetTextHeight("M") >> 1);
IntrAllocColor(PUMenu -> XorColor, INTR_INTENSITY_VHIGH);
delay(25);
IntrInputFlush();
while (!Exit) {
switch (Event) {
case INTR_EVNT_SELECT:
/* We are on list item - need to return its index. */
if (MatchIndex >= 0) {
RetVal = TRUE;
PUMenu -> SelectedIndex = MatchIndex;
Exit = TRUE;
}
else {
GRTone(1500, 100); /* Do some noise... */
GRTone( 500, 200);
}
break;
case INTR_EVNT_ABORT:
RetVal = FALSE;
PUMenu -> SelectedIndex = MatchIndex;
Exit = TRUE;
break;
case INTR_EVNT_MOVE:
NewIndex = MatchPosition(x, y,
ListTop, ListLeft, ListBottom, ListRight,
POP_UP_BASE_LINE, GRGetTextHeight("M"));
if (NewIndex != MatchIndex) {
/* Invert this entry back to original state: */
if (MatchIndex >= 0)
GRXORRectangle(ListLeft - 1,
ListTop + MatchIndex * POP_UP_BASE_LINE - 1,
ListRight + 1,
ListTop + GRGetTextHeight("M") + 1 +
MatchIndex * POP_UP_BASE_LINE);
MatchIndex = NewIndex;
/* Invert this entry: */
if (MatchIndex >= 0)
GRXORRectangle(ListLeft - 1,
ListTop + MatchIndex * POP_UP_BASE_LINE - 1,
ListRight + 1,
ListTop + GRGetTextHeight("M") + 1 +
MatchIndex * POP_UP_BASE_LINE);
}
break;
}
if (!Exit) Event = IntrGetEventWait(&x, &y);
}
MenuEpilog();
return RetVal;
}